package secondriver.qiniucs.client;

import java.math.BigDecimal;
import java.util.HashMap;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
import org.json.JSONObject;

import secondriver.qiniucs.client.MainActivity.FileEntity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.os.Binder;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.util.Log;

import com.qiniu.android.http.ResponseInfo;
import com.qiniu.android.storage.UpCancellationSignal;
import com.qiniu.android.storage.UpCompletionHandler;
import com.qiniu.android.storage.UpProgressHandler;
import com.qiniu.android.storage.UploadManager;
import com.qiniu.android.storage.UploadOptions;

public class UploadService extends Service {

	private static String TAG = "UploadService";

	public static final String ACTION_UPLOAD_SERVCE = "secondriver.service.ACTION_UPLOAD_SERVCE";
	public static final String HTTP_SERVER_URL = "http://qiniucs.sinaapp.com/gptoken";
	public static final String UTF_8 = "UTF-8";

	protected static final int SERVER_ERROR = 0x0001;
	protected static final int TOKEN_ERROR = 0x0002;
	protected static final int UPLOAD_OK = 0x0003;
	protected static final int UPLOAD_PROGRESS = 0x0004;

	private final String CODE = "code";
	private final String TOKEN = "token";

	private final LocalBinder localBinder = new LocalBinder();
	public static HashMap<Integer, Integer> notificationSet = new HashMap<Integer, Integer>();

	private Context ctx;

	private NotificationManager nm;
	private UploadManager uploadManager;
	private Notification.Builder builder;

	private boolean isCancelled = false;

	@Override
	public IBinder onBind(Intent intent) {
		Log.i(TAG, "onBind");
		return localBinder;
	}

	@Override
	public void onCreate() {
		Log.i(TAG, "onCreate");
		super.onCreate();
		nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
		this.ctx = this;
		this.builder = new Notification.Builder(ctx)
				.setLights(Color.BLUE, 1000, 400)
				.setSmallIcon(android.R.drawable.stat_sys_upload)
				.setDefaults(Notification.DEFAULT_LIGHTS)
				.setWhen(System.currentTimeMillis()).setAutoCancel(true);
		uploadManager = new UploadManager();
	}

	@Override
	public void onDestroy() {
		Log.i(TAG, "onDestroy");
		super.onDestroy();
	}

	@Override
	public int onStartCommand(Intent intent, int flags, int startId) {
		Log.i(TAG, "onStartCommand");
		return super.onStartCommand(intent, flags, startId);
	}

	private Handler handler = new Handler() {
		public void handleMessage(Message msg) {
			int notificationId = msg.arg1;
			switch (msg.what) {
			case TOKEN_ERROR: {
				nm.notify(notificationId,
						builder.setContentText(getString(R.string.token_error))
								.build());
				nm.cancel(notificationId);
				notificationSet.remove(notificationId);
				break;
			}
			case SERVER_ERROR: {
				nm.notify(
						notificationId,
						builder.setContentText(getString(R.string.server_error))
								.build());
				break;
			}
			case UPLOAD_OK: {
				nm.notify(notificationId,
						builder.setContentText(getString(R.string.upload_over))
								.build());
				notificationSet.remove(notificationId);
				break;
			}
			case UPLOAD_PROGRESS: {
				nm.notify(
						notificationId,
						builder.setContentText(
								getString(R.string.upload_precent).replace("?",
										String.valueOf(msg.arg2))).build());
				break;
			}
			default:
				break;
			}
		};
	};

	public void upload(final FileEntity fileEntity) {
		final int notificationId = fileEntity.getNotificationId();
		final String filePath = fileEntity.getFilePath();
		final String key = fileEntity.getKey();

		if (notificationSet.containsKey(notificationId)) {
			return;
		}
		nm.notify(
				notificationId,
				builder.setTicker(key + getString(R.string.upload_start))
						.setContentTitle(key)
						.setContentText(getString(R.string.upload_ing)).build());
		notificationSet.put(notificationId, notificationId);

		new Thread(new Runnable() {

			@Override
			public void run() {

				try {
					HttpGet get = new HttpGet(HTTP_SERVER_URL);
					DefaultHttpClient client = new DefaultHttpClient();
					HttpResponse response = client.execute(get);
					if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
						HttpEntity entity = response.getEntity();
						String result = EntityUtils.toString(entity, UTF_8);
						JSONObject o = new JSONObject(result);
						int code = o.getInt(CODE);
						String token = o.getString(TOKEN);
						Log.i(TAG, o.toString());
						if (code == 1) {
							uploadManager
									.put(filePath,
											key,
											token,
											new QiniuUpCompletionHandler(
													notificationId),
											new UploadOptions(
													null,
													fileEntity.getMimeType(),
													true,
													new QiniuUpProgressHandler(
															notificationId),
													new QiniuUpCancellationSignal()));
						} else {
							Message m = Message.obtain(handler, TOKEN_ERROR);
							m.arg1 = notificationId;
							m.sendToTarget();
						}

					}
				} catch (Exception e) {
					e.printStackTrace();
					Message m = Message.obtain(handler, SERVER_ERROR);
					m.arg1 = notificationId;
					m.sendToTarget();
				}
			}
		}).start();
	}

	public class LocalBinder extends Binder {
		public UploadService getService() {
			return UploadService.this;
		}
	}

	class QiniuUpCompletionHandler implements UpCompletionHandler {

		private Integer notificationId;

		public QiniuUpCompletionHandler(Integer notificationId) {
			this.notificationId = notificationId;
		}

		@Override
		public void complete(String key, ResponseInfo responseInfo,
				JSONObject jsonObject) {
			Message m = Message.obtain(handler, UPLOAD_OK);
			m.arg1 = notificationId;
			m.sendToTarget();
		}
	}

	class QiniuUpProgressHandler implements UpProgressHandler {

		private Integer notificationId;

		public QiniuUpProgressHandler(Integer notificationId) {
			this.notificationId = notificationId;
		}

		@Override
		public void progress(String key, double precent) {
			if (new BigDecimal(precent).compareTo(new BigDecimal(1.0D)) == 0) {
				Log.i(TAG, "progress over.");
				Message m = Message.obtain(handler, UPLOAD_OK);
				m.arg1 = notificationId;
				m.sendToTarget();
			} else {
				Log.i(TAG, "progress " + precent);
				Message m = Message.obtain(handler, UPLOAD_PROGRESS);
				m.arg1 = notificationId;
				m.arg2 = (int) (precent * 100);
				m.sendToTarget();
			}
		}
	}

	class QiniuUpCancellationSignal implements UpCancellationSignal {

		@Override
		public boolean isCancelled() {
			return isCancelled;
		}
	}

}
